#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time    : 2018/1/4 0004 16:42
# @Author  : Arliki
# @email   : hkdnxycz@outlook.com
# @File    : wxpub.py
import random
import hashlib
import pycurl
import io
import time
import xml.sax as xmlsax
import pymysql
import json


class XMLHandler(xmlsax.handler.ContentHandler):
    def __init__(self):
        self.buffer = ""
        self.mapping = {}

    def startElement(self, name, attributes):
        self.buffer = ""

    def characters(self, data):
        self.buffer += data

    def endElement(self, name):
        self.mapping[name] = self.buffer

    def getDict(self):
        return self.mapping
class Wxpub():
    def __init__(self):
        self.__key = "A870D8974F4091139FD6A3BA40B865E7"
        self.__appid = "wxf4c3e46ec2e0cb3e"
        self.__mchid = "1486749382"

    # 处理退款
    def refund(self, sed):
        sed["sign"] = self.get_sign(sed)
        xml = self.dic_to_xml(sed).encode('utf-8')
        data = self.get_result(xml)
        return data

    # 获取签名
    def get_sign(self, sed, reverse=False):
        sed["appid"] = self.__appid
        sed["mch_id"] = self.__mchid
        sed["nonce_str"] = self.get_noncestr(20)
        # 排序拼接字符串
        dic = self.dict_sort(sed, reverse=reverse)
        strs = self.dic_to_str(dic)
        # 添加keys md5加密 转大写
        strs = strs + "&key=" + self.__key
        sign = self.md5(strs).upper()
        return sign

    # 获取微信返回结果
    def get_result(self, xml):
        b = io.BytesIO()
        url = "https://api.mch.weixin.qq.com/secapi/pay/refund"
        curl = pycurl.Curl()
        curl.setopt(pycurl.URL, url)
        curl.setopt(pycurl.HEADER, 0)
        curl.setopt(pycurl.SSLKEYTYPE, "PEM")
        curl.setopt(pycurl.SSLKEY, './cert/apiclient_key.pem')
        curl.setopt(pycurl.SSLCERTTYPE, "PEM")
        curl.setopt(pycurl.SSLCERT, './cert/apiclient_cert.pem')
        curl.setopt(pycurl.SSLCERTTYPE, "PEM")
        curl.setopt(pycurl.CAINFO, './cert/rootca.pem')
        curl.setopt(pycurl.POST, 1)
        curl.setopt(pycurl.POSTFIELDS, xml)
        curl.setopt(pycurl.WRITEFUNCTION, b.write)
        curl.perform()
        data = b.getvalue()
        xh = XMLHandler()
        xmlsax.parseString(data, xh)
        data = xh.getDict()
        return data

    # 获取随机数 <=32位
    def get_noncestr(self, length=32):
        chars = "1234567890qwertyuioplkjhgfdsazxcvbnm"
        strs = ""
        for x in range(length):
            strs += chars[random.randrange(0, len(chars))]
        return strs

    # 字典转xml
    def dic_to_xml(self, arr):
        xml = "<xml>"
        for k, v in arr.items():
            if isinstance(v, dict):
                xml += ("<{0}>{1}</{0}>".format(k, self.dic_to_xml(v)))
            else:
                if v.isdigit():
                    xml += ("<{0}>{1}</{0}>".format(k, v))
                else:
                    xml += ("<{0}><![CDATA[{1}]]></{0}>".format(k, v))
        xml += ("</xml>")
        return "".join(xml)

    # 字典排序 默认升序 降序为True
    def dict_sort(self, dic, reverse=False):
        n_dic = {}
        k = sorted(dic, reverse=reverse)
        for i in k:
            n_dic[i] = dic[i]
        return n_dic

    # 字典组成字符串
    def dic_to_str(self, dic):
        strs = ""
        for k, v in dic.items():
            strs = strs + k + "=" + str(v) + "&"
        strs = strs[0:len(strs) - 1]
        return strs

    # md5
    def md5(self, strs):
        if isinstance(strs, (str, bytes)):
            strs = strs.encode('utf-8')
            m = hashlib.md5()
            m.update(strs)
            return m.hexdigest()


def run():
    con = pymysql.connect(host='', user='arliki', passwd='', db='youxian', charset='utf8')
    cursor = con.cursor()
    num = cursor.execute("select user_id,price,order_sn,id,act_id from ecs_wxrefun where status=0 and refun_time='000'")
    if num > 0:
        for row in cursor.fetchall():
            sed = {}
            sed["out_trade_no"] = sed["out_refund_no"] = row[2]
            sed["total_fee"] = sed["refund_fee"] = str(int(row[1] * 100))
            if row[4] > 0:
                sed["refund_desc"] = "未中奖退款"
            elif row[4] == -1:
                sed["refund_desc"] = "拼单幸运用户"
            else:
                sed["refund_desc"] = "拼单失败退款"
            data = Wxpub().refund(sed)
            gmtime = time.strftime("%Y/%m/%d %H:%M:%S", time.localtime())
            write_name = int(time.strftime('%Y%m%d', time.localtime()))
            # print(data)
            if data["return_code"] == "SUCCESS":
                try:
                    time1 = int(time.time())
                    sql = "update ecs_wxrefun set status=12,refun_time='%s' where user_id='%s' and id = '%s'" % (
                    time1, row[0], row[3])
                    print(sql)
                    cursor.execute(sql)
                    con.commit()
                    with open("%s.log" % write_name, "a+", encoding="utf8") as f:
                        f.write("\nok_%s:%s_%s" % (row[0], data['total_fee'], gmtime))
                except:
                    con.rollback()
                    with open("%s.log" % write_name, "a+", encoding="utf8") as f:
                        f.write("\noerror_%s:%s_%s" % (row[0], str(data), gmtime))
            else:
                with open("%s.log" % write_name, "a+", encoding="utf8") as f:
                    f.write("\nerror_%s:%s_%s" % (row[0], str(data), gmtime))
    cursor.close()
    con.close()


if __name__ == '__main__':
    while True:
        run()
        exit()
        # time.sleep(30 * 60)
